﻿using UnityEngine;
using UnityEngine.UI;
using System.Collections;

//[RequireComponent(typeof(AudioSource))]
public class PlayerController : MonoBehaviour 
{
    // Objecto Rigibody para associar ao objecto Jogador (Esfera)
    // Pública para ser acessada no Unity
    public Rigidbody Player;

    // Objecto para procurar o GameObject Main Camera
    private GameObject MainCamera;

    // Objecto para usar o GameObject Main Camera e ter acesso às suas propriedades e variáveis
    private CameraController MainCameraController;

    public Canvas WinMenu;

    private PlayerController PlayerScript;

    private float MoveHorizontal;
    private float MoveVertical;

    public AudioClip HitSound;
    public AudioClip BeginSound;
    public AudioClip EndSound;
    public AudioSource AudioSound;

    // Variável de velocidade para definir no leitor
    // Pública para ser acessada no Unity
    public float Speed;

    // Váriável para definir a massa (Peso) do objecto Jogador (Esfera)
    // Pública para ser acessada no Unity
    public float Mass;

    public float JumpSpeed;
    private bool IsGrounded = true;

    // Objecto GameObject em Array 
    private GameObject[] PickUps;

    // Variável para armazenar o tamanho do Array do objecto GameObject (Total de PickUps)
    private int Total;

    // Varável de contagem de PickUps
    private int CountPickups;

    // Objecto Text para associar ao objecto UI Text (Contagem de PickUps)
    // Pública para ser acessada no Unity
    public Text CountText;

    // Objecto Text para associar ao objecto UI Text (Game Over)
    // Pública para ser acessada no Unity
    public Text FinishText;

    void Awake()
    {
        // Procurar o GameObject Main Camera
        MainCamera = GameObject.Find("Main Camera");

        // Usar o GameObject Main Camera e encontrar o script CameraController desse objecto para ter acesso às suas propriedades e variáveis
        MainCameraController = MainCamera.GetComponent<CameraController>();
    }

    // Função chamada apenas uma vez ao arranque
    void Start()
    {
        // Ocultar cursor do rato
        Cursor.visible = false;

        WinMenu = WinMenu.GetComponent<Canvas>();

        WinMenu.enabled = false;

        PlayerScript = GetComponent<PlayerController>();

        AudioSound = GetComponent<AudioSource>();

        // Iniciar o Jogador (Esfera) com a massa (Peso) definida no Unity
        Player.mass = Mass;    

        // Inicar a contagem de PickUps a 0
        CountPickups = 0;

        // Iniciar o texto de contagem de PickUps
        CountText.text = "Contagem: 0";

        // Iniciar o texto de fim de jogo vazio
        FinishText.text = "";

        // Procurar todos os GameObjects com a Tag PickUp e definir essa informação no Array do objecto GameObject
        PickUps = GameObject.FindGameObjectsWithTag("PickUp");

        // Definir a varíavel Total com o tamanho do Array do objecto GameObject (Total de PickUps)
        Total = PickUps.Length;

        AudioSound.PlayOneShot(BeginSound, 1f);
    }

    // Função chamada antes de cada Frame e antes de qualquer cálculo de física
    void FixedUpdate()
    {
        if (PlayerPrefs.HasKey("FPS"))
        {
            if (PlayerPrefs.GetInt("FPS") == 1)
                this.transform.rotation = Quaternion.Euler(0, MainCameraController.CurrentYRotation, 0);
        }

        // Movimento Horizontal (Teclas A e D e Setas Direita/Esquerda)
        MoveHorizontal = Input.GetAxis("Horizontal");

        // Movimento Vertical (Teclas W e S e Setas Cima/Baixo)
        MoveVertical = Input.GetAxis("Vertical");

        // Criar Vector 3D para calcular o movimento
        Vector3 Movement = new Vector3(MoveHorizontal, 0.0f, MoveVertical);

        // Se o modo FPS estiver activado
        if (PlayerPrefs.HasKey("FPS"))
        {
            if (PlayerPrefs.GetInt("FPS") == 1)
                // Aplicar força relativamente à direcção em que a camera esta apontada
                // Aplicar força ao objecto Rigidbody associado ao objecto Jogador (Esfera), nas direcções do Vector 3D, com a velocidade definida no leitor e suavemente de acordo com a framerate
                Player.AddRelativeForce(Movement * Speed * Time.deltaTime);
        }

        // Se o modo FPS estiver desactivado
        if (PlayerPrefs.HasKey("FPS"))
        {
            if (PlayerPrefs.GetInt("FPS") == 0)
                // Aplicar de forma simples
                // Aplicar força ao objecto Rigidbody associado ao objecto Jogador (Esfera), nas direcções do Vector 3D, com a velocidade definida no leitor e suavemente de acordo com a framerate
                Player.AddForce(Movement * Speed * Time.deltaTime);
        }

        if (Input.GetButtonDown("Jump") && IsGrounded == true)
            Player.velocity += JumpSpeed * Vector3.up;
        else
            Player.velocity -= 1 * Vector3.up;
    }

    void Update()
    {
        if (Input.GetKey("escape"))
        {
            PauseMenu();
            Debug.Log("Button Registered");
        }
    }

    void OnCollisionStay(Collision collisionInfo)
    {
        IsGrounded = true;
    }

    void OnCollisionExit(Collision collisionInfo)
    {
        IsGrounded = false;
    }

    // Função chamada quando o Collider do GameObject Jogador (Esfera (Player)) entra no Trigger de outro Collider do GameObject (_gameObject)
    void OnTriggerEnter(Collider _gameObject)
    {
        // Se a Tag do GameObject "colidido" for PickUp
        if (_gameObject.gameObject.tag == "PickUp")
        {
            AudioSound.PlayOneShot(HitSound, 1f);

            // Desactivar (Não Destrói) o GameObject (_gameObject) com a Tag PickUp
            _gameObject.gameObject.SetActive(false);            

            // Incrementar a 1 a contagem de PickUps por cada GameObject (_gameObject) com a Tag PickUp desactivado (apanhado)
            CountPickups++;

            // Desincrementar a 1 a variável do total de PickUps por cada PickUp apanhada
            Total--;

            // Chamar a função de actualização para o texto da contagem de PickUps
            PickupCount();

            // Se o total de PickUps no mapa for 0
            if (Total == 0)
            {
                // Chamar a função para exibir o texto de fim de jogo no ecrã quando já não existir PickUps no mapa
                Finish();
            }
        }
    }

    // Função chamada na Função OnTriggerEnter para actualizar o texto de contagem de PickUps
    void PickupCount ()
    {
        // Definir o texto de contagem de PickUps
        CountText.text = "Contagem: " + CountPickups.ToString();
    }

    // Função chamada na Função OnTriggerEnter para exibir o texto de fim de jogo no ecrã quando já não existir PickUps no mapa
    void Finish()
    {
        AudioSound.PlayOneShot(EndSound, 1f);

        Cursor.visible = true;

        // Definir o texto de fim de jogo
        FinishText.text = "Apanhaste todos os quadrados!";

        WinMenu.enabled = true;

        PlayerScript.enabled = false;
    }

    void PauseMenu()
    {
        Cursor.visible = true;

        FinishText.text = "Jogo Pausado";

        WinMenu.enabled = true;

        Player.gameObject.SetActive(false);
    }
}
